#include "../mq_server/virtualhost.h"
#include <gtest/gtest.h>
using namespace ns_virtual;

class HostTest : public testing::Test
{
public:
    void SetUp() override
    {
        std::unordered_map<std::string, std::string> empty_map;
        _host = std::make_shared<VirtualHost>("./data/message/", "./data/host1.db");
        _host->declare_exchange("exchange1", ExchangeType::DIRECT, true, false, empty_map);
        _host->declare_exchange("exchange2", ExchangeType::DIRECT, true, false, empty_map);
        _host->declare_exchange("exchange3", ExchangeType::DIRECT, true, false, empty_map);

        _host->declare_queue("queue1", true, false, false, empty_map);
        _host->declare_queue("queue2", true, false, false, empty_map);
        _host->declare_queue("queue3", true, false, false, empty_map);

        _host->declare_bind("exchange1", "queue1", "news.music.#");
        _host->declare_bind("exchange1", "queue2", "news.music.#");
        _host->declare_bind("exchange1", "queue3", "news.music.#");

        _host->declare_bind("exchange2", "queue1", "news.music.#");
        _host->declare_bind("exchange2", "queue2", "news.music.#");
        _host->declare_bind("exchange2", "queue3", "news.music.#");

        _host->declare_bind("exchange3", "queue1", "news.music.#");
        _host->declare_bind("exchange3", "queue2", "news.music.#");
        _host->declare_bind("exchange3", "queue3", "news.music.#");

        _host->insert_msg("queue1", nullptr, "Hello World-1");
        _host->insert_msg("queue1", nullptr, "Hello World-2");
        _host->insert_msg("queue1", nullptr, "Hello World-3");

        _host->insert_msg("queue2", nullptr, "Hello World-1");
        _host->insert_msg("queue2", nullptr, "Hello World-2");
        _host->insert_msg("queue2", nullptr, "Hello World-3");

        _host->insert_msg("queue3", nullptr, "Hello World-1");
        _host->insert_msg("queue3", nullptr, "Hello World-2");
        _host->insert_msg("queue3", nullptr, "Hello World-3");
    }
    void TearDown() override
    {
        _host->clear();
    }

public:
    shared_ptr<VirtualHost> _host;
};

TEST_F(HostTest, init_test)
{
    ASSERT_EQ(_host->exist_exchange("exchange1"), true);
    ASSERT_EQ(_host->exist_exchange("exchange2"), true);
    ASSERT_EQ(_host->exist_exchange("exchange3"), true);

    ASSERT_EQ(_host->exist_queue("queue1"), true);
    ASSERT_EQ(_host->exist_queue("queue2"), true);
    ASSERT_EQ(_host->exist_queue("queue3"), true);

    ASSERT_EQ(_host->exist_binding("exchange1", "queue1"), true);
    ASSERT_EQ(_host->exist_binding("exchange1", "queue2"), true);
    ASSERT_EQ(_host->exist_binding("exchange1", "queue3"), true);

    ASSERT_EQ(_host->exist_binding("exchange2", "queue1"), true);
    ASSERT_EQ(_host->exist_binding("exchange2", "queue2"), true);
    ASSERT_EQ(_host->exist_binding("exchange2", "queue3"), true);

    ASSERT_EQ(_host->exist_binding("exchange3", "queue1"), true);
    ASSERT_EQ(_host->exist_binding("exchange3", "queue2"), true);
    ASSERT_EQ(_host->exist_binding("exchange3", "queue3"), true);

    MessagePtr msg1 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
    MessagePtr msg2 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));
    MessagePtr msg3 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));
    MessagePtr msg4 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg4.get(), nullptr);
}

TEST_F(HostTest, remove_exchange)
{
    _host->delete_exchange("exchange1");
    ASSERT_EQ(_host->exist_binding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->exist_binding("exchange1", "queue2"), false);
    ASSERT_EQ(_host->exist_binding("exchange1", "queue3"), false);
}

TEST_F(HostTest, remove_queue)
{
    _host->delete_queue("queue1");
    ASSERT_EQ(_host->exist_binding("exchange1", "queue1"), false);
    ASSERT_EQ(_host->exist_binding("exchange2", "queue1"), false);
    ASSERT_EQ(_host->exist_binding("exchange3", "queue1"), false);

    MessagePtr msg1 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg1.get(), nullptr);
}

TEST_F(HostTest, ack_message)
{
    MessagePtr msg1 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg1->payload().body(), std::string("Hello World-1"));
    _host->comfirm_msg(std::string("queue1"), msg1->payload().attributes().id());

    MessagePtr msg2 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg2->payload().body(), std::string("Hello World-2"));
    _host->comfirm_msg(std::string("queue1"), msg2->payload().attributes().id());

    MessagePtr msg3 = _host->que_front_msg("queue1");
    ASSERT_EQ(msg3->payload().body(), std::string("Hello World-3"));
    _host->comfirm_msg(std::string("queue1"), msg3->payload().attributes().id());
}

int main(int argc, char *argv[])
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();

}